package com.simpleim.starter.server;

import com.simpleim.im.common.bean.User;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class ServerSession {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerSession.class);

    private User user;

    private Channel channel;

    private String sessionId;

    private boolean isLogin;

    public static final AttributeKey<String> KEY_USER_ID = AttributeKey.newInstance("key_user_id");

    public static final AttributeKey<ServerSession> KEY_SESSION = AttributeKey.newInstance("serversession_key");

    private Map<String, Object> params = new HashMap<>();

    public ServerSession(Channel channel) {
        this.channel = channel;
        this.sessionId = buildSessionId();
    }

    public String buildSessionId() {
        String random = UUID.randomUUID().toString();
        return random.replace("-", "");
    }

    public void close() {
        ChannelFuture future = channel.close();
        future.addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (!future.isSuccess()) {
                    LOGGER.error("CHANNEL_CLOSED error ");
                }
            }
        });
    }

    public Channel getChannel() {
        return channel;
    }

    /**
     * 绑定
     */
    public void bind() {
        // 登录成功后进行双向绑定
        this.channel.attr(KEY_SESSION).set(this);
        isLogin = true;
        // 将当前session加入map
        SessionMap.inst().addSession(this);
    }

    /**
     * 解绑
     */
    public void unbind() {
        isLogin = false;
        SessionMap.inst().removeSession(sessionId);
        close();
    }

    public static void closeSession(ChannelHandlerContext ctx) {
        // 从ctx获取session
        ServerSession session = ctx.attr(KEY_SESSION).get();
        if (session != null && session.isValid()) {
            session.close();
            SessionMap.inst().removeSession(session.sessionId);
        }
    }

    public synchronized void setKey(String key, Object msg) {
        params.put(key, msg);
    }

    public synchronized Object getKey(String key) {
        if (params.containsKey(key))
            return params.get(key);
        return null;
    }

    /**
     * 同一个session串行执行
     * @param msg
     */
    public synchronized void writeAndFlush(Object msg) {
        if (channel.isWritable()) {
            channel.writeAndFlush(msg);
        } else {
            LOGGER.debug("通道很忙，消息被暂存了");
        }
    }

    public boolean isValid() {
        return user != null;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
        user.setSessionId(this.sessionId);
    }

    public String getSessionId() {
        return sessionId;
    }

    public boolean isLogin() {
        return isLogin;
    }
}
